#include <Phaseloss/detect.h>
#include "rtthread.h"
#include <stdio.h>
#include <string.h>
#include "main.h"
#include "stm32f1xx_hal_tim.h"
#include "netupdata.h"
#include "ota.h"


static struct rt_thread detectThread; //线程控制块
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t detectThread_stack[1024]; //线程栈

static rt_timer_t timer1;

TIM_HandleTypeDef g_timx_handle_5;  /* 定时器5句柄 */

int PA8_IT_Count=0;            //PA8引脚跳变次数
int PA8_Arr[31]={0};        //记录每次PA8引脚跳变时时间偏移
int PB8_IT_Count=0;         //PB8引脚跳变次数
int PB8_Arr[31]={0};        //记录每次PB8引脚跳变时时间偏移
int Count=0;
int flag=0;
int detest_test=0;

static int updataFlag=0;

static void upData()
{
    rt_kprintf("UP detect\n");
         struct UpEvents updata = { .BizType = 3, //触发类型为 异常触发
                 .EventType = 6, //事件类型为 缺相告警
                 .CtrlPort = 0 };
         updata_EventStruct_Set(&updata); //设置数据同时通知上报
}

static void timeout1(void *parameter)
{
    if (updataFlag == 1)
    {
        upData();

    }
}


int getTimeData(){
    PA8_IT_Count = 0;                //变量初始化
    rt_memset(PA8_Arr, 0, sizeof(PA8_Arr));
    PB8_IT_Count = 0;
    rt_memset(PB8_Arr, 0, sizeof(PB8_Arr));

    detest_test = 1;
    Count = 0;
    flag = 0;
    int result=0;
    DetestGPIO_init_PB8();
    __HAL_TIM_SET_COUNTER(&g_timx_handle_5, 0); /* 定时器5计数器清零 */
    __HAL_TIM_ENABLE(&g_timx_handle_5); /* 使能定时器 */
    HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); /* 使能外部中断线10-15 */
    while (flag == 0)
    {                                                             //等待检测到30次跳变
        rt_thread_mdelay(50);
        //printf("Testing....\r\n");
    }

    detest_test = 2;
    Count = 0;
    flag = 0;
    DetestGPIO_init_PA8();
    __HAL_TIM_SET_COUNTER(&g_timx_handle_5, 0); /* 定时器5计数器清零 */
    __HAL_TIM_ENABLE(&g_timx_handle_5); /* 使能定时器 */
    HAL_NVIC_EnableIRQ(EXTI9_5_IRQn); /* 使能外部中断线10-15 */
    while (flag == 0)
    {                                                             //等待检测到30次跳变
        rt_thread_mdelay(50);
        //printf("Testing....\r\n");
    }

    int sum_high_PA8 = 0;                        //保存PA8的15次高电平时间
    int sum_low_PA8 = 0;            //保存PA8的15次低电平时间
    int sum_high_PB8 = 0;
    int sum_low_PB8 = 0;
    //下标为0对应元素为高电平区间的起始点时间偏移
    //下标为1对应元素为高电平区间的终止点时间偏移，低电平区间的起始点时间偏移
    //下标为2对应元素为低电平区间的终止点时间偏移
    for (int i = 1; i < 31; i++)
    {
        if (i % 2 == 0)
        {            //偶数下标为低电平区间的终止点
            sum_low_PA8 += PA8_Arr[i] - PA8_Arr[i - 1];
            sum_low_PB8 += PB8_Arr[i] - PB8_Arr[i - 1];
        }
        else
        {           //偶数下标为高电平区间的终止点
            sum_high_PA8 += PA8_Arr[i] - PA8_Arr[i - 1];
            sum_high_PB8 += PB8_Arr[i] - PB8_Arr[i - 1];
        }

    }
    if (PA8_IT_Count <= 5)
    {           //100*65536  大概6秒，如果6秒内检测不到5次跳变视为恒压
        if (HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8) == 1)
        {
            rt_kprintf("PA8 always is High Level!\r\n");
        }
        else
        {
            rt_kprintf("PA8 always is Low Level!\r\n");
        }
    }
    else
    {
        //(PA8_IT_Count/2)整数相除舍去小数部分，表示高电平次数，PA8_IT_Count==2或3的时候表示获取一次高电平
        //((PB8_IT_Count-1)/2)整数相除舍去小数部分，表示高电平次数，PA8_IT_Count==3或4的时候表示获取一次低电平
        rt_kprintf("PA8 high %d\t low %d\t\n", sum_high_PA8 / ((PA8_IT_Count / 2)) ,
                sum_low_PA8 / (((PA8_IT_Count - 1) / 2)) );

    }
    if (PB8_IT_Count <= 5)
    {
        if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == 1)
        {
            rt_kprintf("PB8 always is High Level!\r\n");
        }
        else
        {
            rt_kprintf("PB8 always is Low Level!\r\n");
        }

    }
    else
    {
        char buff[128];

        sprintf(buff,"PB8 high %d\t low %d\t\n", sum_high_PB8 / ( (PB8_IT_Count / 2)) ,
                sum_low_PB8 / ( ((PB8_IT_Count - 1) / 2)) );
        rt_kprintf(buff);

    }

    if (PA8_IT_Count != 31 || PB8_IT_Count != 31)
    {
        result = 1;

    }
    else
    {
        int temp = 0;
        int High_A = sum_high_PA8 / ((PA8_IT_Count / 2));
        int Low_A = sum_low_PA8 / (((PA8_IT_Count - 1) / 2));
        int High_B = sum_high_PB8 / ((PB8_IT_Count / 2));
        int Low_B = sum_low_PB8 / (((PB8_IT_Count - 1) / 2));
        int Diff_A = High_A - Low_A;
        if (Diff_A < 0)
            Diff_A *= -1;
        int Diff_B = High_B - Low_B;
        if (Diff_B < 0)
            Diff_B *= -1;
        if (Diff_A * 15 / (High_A + Low_A) >= 2 || Diff_B * 15 / (High_B + Low_B) >= 2)
        {
            temp = 1;
        }
        int temp_count = 0;
        for (int i = 0; i < 16; i++)
        {
            if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8) == HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_8))
            {
                temp_count++;
            }
            rt_thread_mdelay(1);
        }
        if (temp_count > 8)
            temp = 1;
        if (temp == 1)
        {
            result = 1;
            rt_kprintf("&&&%dUPPPPPPPPPPPPPPPPPPPPPP\n", temp_count);


        }

    }

    return result;

}

void DetestTimer_init()
{
    __HAL_RCC_TIM5_CLK_ENABLE();                                 /* 使能TIMx时钟 */
    g_timx_handle_5.Instance = TIM5;                             /* 通用定时器x */
    g_timx_handle_5.Init.Prescaler = 72-1;                       /* 预分频系数 */
    g_timx_handle_5.Init.CounterMode = TIM_COUNTERMODE_UP;       /* 递增计数模式 */
    g_timx_handle_5.Init.Period = 0xFFFF;                        /* 自动装载值 */
    HAL_TIM_Base_Init(&g_timx_handle_5);

    HAL_NVIC_SetPriority(TIM5_IRQn, 1, 3);                       /* 设置中断优先级，抢占优先级1，子优先级3 */
    HAL_NVIC_EnableIRQ(TIM5_IRQn);                               /* 开启ITMx中断 */
    HAL_TIM_Base_Start_IT(&g_timx_handle_5);                     /* 使能定时器5更新中断 */
}

void DetestGPIO_init_PA8()
{
    GPIO_InitTypeDef gpio_init_struct;//

    __HAL_RCC_GPIOA_CLK_ENABLE();
    gpio_init_struct.Pin = GPIO_PIN_8;
    gpio_init_struct.Mode = GPIO_MODE_IT_RISING_FALLING;            /* 边沿沿触发 */
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOA, &gpio_init_struct);                        /* PB8配置为边沿触发中断 */

    __HAL_RCC_GPIOB_CLK_ENABLE();
    gpio_init_struct.Pin = GPIO_PIN_8;
    gpio_init_struct.Mode = GPIO_MODE_INPUT;
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOB, &gpio_init_struct);                        /* PA8配置为边沿触发中断 */

    HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 2);                     /* 抢占0，子优先级2 */
}
void DetestGPIO_init_PB8()
{
    GPIO_InitTypeDef gpio_init_struct;//

    __HAL_RCC_GPIOA_CLK_ENABLE();
    gpio_init_struct.Pin = GPIO_PIN_8;
    gpio_init_struct.Mode = GPIO_MODE_INPUT;
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOA, &gpio_init_struct);                        /* PB8配置为边沿触发中断 */

    __HAL_RCC_GPIOB_CLK_ENABLE();
    gpio_init_struct.Pin = GPIO_PIN_8;
    gpio_init_struct.Mode = GPIO_MODE_IT_RISING_FALLING;            /* 边沿沿触发 */
    gpio_init_struct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOB, &gpio_init_struct);                        /* PA8配置为边沿触发中断 */

    HAL_NVIC_SetPriority(EXTI9_5_IRQn, 0, 2);                     /* 抢占0，子优先级2 */
}

void EXTI9_5_IRQHandler(void)
{

    HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_8);
}

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if(detest_test==1&&GPIO_Pin==GPIO_PIN_8)                       //PB8
    {
              //HAL_GPIO_ReadPin(GPIOC,GPIO_PIN_10)==1确保上升沿的时候开始计数
        if(PB8_IT_Count!=0||HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_8)==1){
            if(PB8_IT_Count<31){            //最多记录31次跳变沿
                PB8_Arr[PB8_IT_Count]=Count*65535+__HAL_TIM_GET_COUNTER(&g_timx_handle_5);
                PB8_IT_Count++;
            }
        }
    }
    else if(detest_test==2&&GPIO_Pin==GPIO_PIN_8)     //PA8
    {
        if(PA8_IT_Count!=0||HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_8)==1){
            if(PA8_IT_Count<31){
                PA8_Arr[PA8_IT_Count]=Count*65535+__HAL_TIM_GET_COUNTER(&g_timx_handle_5);
                PA8_IT_Count++;
            }
        }
    }
        //统计6秒后，或者两个引脚均检测到31次跳变时关闭外部中断
    if(Count>=50||(PA8_IT_Count==31&&PB8_IT_Count==31))
    {
        HAL_NVIC_DisableIRQ(EXTI9_5_IRQn);                  /* 关闭外部中断 */
        __HAL_TIM_DISABLE(&g_timx_handle_5);          /* 关闭定时器 */
        __HAL_TIM_SET_COUNTER(&g_timx_handle_5, 0);   /* 定时器5计数器清零 */
        flag=1;
    }
}


void TIM5_IRQHandler(void)
{
    /* 以下代码没有使用定时器HAL库共用处理函数来处理，而是直接通过判断中断标志位的方式 */
    if(__HAL_TIM_GET_FLAG(&g_timx_handle_5, TIM_FLAG_UPDATE) != RESET)
    {
        Count++;    //存储定时器溢出次数
        __HAL_TIM_CLEAR_IT(&g_timx_handle_5, TIM_IT_UPDATE);  /* 清除定时器溢出中断标志位 */
              if(Count>=100){
                      HAL_NVIC_DisableIRQ(EXTI9_5_IRQn);                      /* 关闭外部中断 */
                        __HAL_TIM_DISABLE(&g_timx_handle_5);          /* 关闭定时器 */
                        __HAL_TIM_SET_COUNTER(&g_timx_handle_5, 0);   /* 定时器5计数器清零 */
                        flag=1;
                }
    }
}


static void detectThreadEntry(void* parameter)
{
    rt_thread_mdelay(5000);
    rt_thread_mdelay(5000);
    rt_thread_mdelay(5000);

    rt_kprintf("[PhaseDetect]phase detect begin\n");
    while (1)
    {
        int DetesctNum = 3;
        int Tcount = 0;
        while (DetesctNum--)
        {
            if (otaStatusGet() == 0)
            {
                if (getTimeData())
                {
                    Tcount = (Tcount >= 3) ? Tcount : Tcount + 1;
                }
                else
                {
                    Tcount = (Tcount <= 0) ? Tcount : (Tcount - 1);
                }

            }
            else
            {
                HAL_NVIC_DisableIRQ(EXTI9_5_IRQn); /* 关闭外部中断 */
                __HAL_TIM_DISABLE(&g_timx_handle_5); /* 关闭定时器 */
                __HAL_TIM_SET_COUNTER(&g_timx_handle_5, 0); /* 定时器5计数器清零 */

            }
            rt_thread_mdelay(1000);
        }
        if (Tcount >= 3) //三次全为异常则上报
        {
            if (updataFlag == 0) //首次检测到缺相
            {
                upData();
                if (timer1 != NULL)
                    rt_timer_start(timer1);
                updataFlag = 1;  //后续5分钟上报一次
            }
        }
        else
        {
            if (updataFlag == 1)
            {
                if (timer1 != NULL)
                    rt_timer_stop(timer1);
            }
            updataFlag = 0;

        }

    }

}
int phaseDetectInit()
{
    DetestTimer_init();


    rt_thread_init(&detectThread, "detectThre", detectThreadEntry,
    RT_NULL, &detectThread_stack[0], sizeof(detectThread_stack), 14, 15);


    timer1 = rt_timer_create("timer", timeout1,
                                 RT_NULL, 5*1000*60,
                                 RT_TIMER_FLAG_PERIODIC);
    if (timer1 == RT_NULL)
    {
        rt_kprintf("create detect timer failed.\n");
        return -1;
    }

    if (RT_EOK != rt_thread_startup(&detectThread))
    {
        rt_kprintf("detectThre Init err\n");
        return 1;
    }
    return 0;
}

//INIT_APP_EXPORT(phaseDetectInit);
